home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Night Owl 6
/
Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso
/
007a
/
gmd_200.zip
/
GMD.C
next >
Wrap
C/C++ Source or Header
|
1991-02-24
|
39KB
|
1,141 lines
/* ************************************************************************
* *
* Grunged Message Delete Utility *
* *
* This program was compiled using Borland's Turbo-C++ version 1 with *
* the tiny memory model. On the author's machine it compiles with *
* no errors or warnings. *
* *
* *
* Warning: *
* *
* This code uses un-documented features of DOS to perform the fast *
* mode message scanning. While these un-documented features have *
* been around and not changed, future releases of DOS may change *
* the way these features work. For reference, the un-documented *
* features used are: *
* *
* 1) This program uses two un-documented fields in the reserved *
* part (the first 21 bytes) of the DTA for the file find first/ *
* next DOS function (Int 21h, Functions 4Eh/4Fh). Those field *
* offsets and their meaning are: *
* *
* a) Word at offset 13 *
* This is the directory entry number within the directory *
* of the current matching entry. The directory entry number *
* starts at 0 for the first entry and increases by one for *
* each subsequent entry regardless of how the directory *
* entry is used or not used. It continues incrementing past *
* sector/cluster boundaries. This is how the find next *
* functions knows where to pick up the search. *
* b) Word at offset 15 *
* This is the cluster number of the first cluster of the *
* directory containing the matching entry. No matter which *
* directory entry number matches, this is always the first *
* cluster. When the directory is the root directory, this *
* number is 0. *
* *
* 2) This program uses DOS Int 21h Function 32h (Get Drive Parameter *
* Block). On entry, AH=32h and DL=drive number (0=default, 1=A, *
* etc.). On return, AL contains FFh if the drive was invalid and *
* DS:BX points to the data structure described by *
* 'drive_parm_struct' defined below. The meaning of the fields *
* is is easily discerned from the field name. A complete *
* description of this function is contained in Terry Dettmann's *
* "DOS Programmer's Reference". *
* *
* 3) This program uses the FAT. It can handle the 12-bit and 16-bit *
* formats. A complete description of the FAT and how it works *
* can also be found in Terry Dettmann's book (see above). *
* *
* Don't play poker with the devil. If you have a version of DOS *
* which is strange, do not use the '-f' switch. If you see the *
* warning message 'Note: Fast mode disabled.' or the program locks *
* up, stop using the '-f' switch. *
* *
* David Troendle *
* New Orleans, LA, USA *
* November, 1990 *
************************************************************************ */
/* Maintenance History:
01/26/91 - GMD got confused by -d<areaname> and -date:n. When it saw
-date:n, it picked up the "ate:n" as an area.
02/12/91 - ConfMail and MRen place comments in Areas.Bbs starting with
a "-". GMD now detects lines starting with "-" as a comment.
02/12/91 - GMD created bad filenames when it attempted to move messages
in an echo name which contained illegal DOS filename
characters.
---------------------------Release 1.01---------------------------
02/24/91 - Added processing for the EchoToss log. Only those echos listed
in the file specified by the -e switch are processed. Those
files are processed from the LastRead pointer in 1.MSG in that
area.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <dir.h>
#include <dos.h>
#include <io.h>
#include <conio.h>
#define MAX_ECHONAME_LENGTH 256
#define MAX_FILENAME_LENGTH 256
#define MAX_TOKEN_SIZE 2048
#define SMALL_FAT_MAX_CLUSTERS 4087
typedef
struct FIDO_message_attribute_struct
{
unsigned Private : 1;
unsigned Crash : 1;
unsigned Recd : 1;
unsigned Sent : 1;
unsigned FileAttached : 1;
unsigned InTransit : 1;
unsigned Orphan : 1;
unsigned KillSent : 1;
unsigned Local : 1;
unsigned HoldForPickup : 1;
unsigned unused : 1;
unsigned FileRequest : 1;
unsigned ReturnReceiptRequest : 1;
unsigned IsReturnReceipt : 1;
unsigned AuditRequest : 1;
unsigned FileUpdateReq : 1;
} FIDO_message_attrib_type;
typedef
struct FIDO_message_struct
{
char fromUserName[36];
char toUserName[36];
char subject[72];
char dateTime[20];
unsigned timesRead;
unsigned destNode;
unsigned origNode;
unsigned cost;
unsigned origNet;
unsigned destNet;
unsigned destZone;
unsigned origZone;
unsigned destPoint;
unsigned origPoint;
unsigned replyTo;
FIDO_message_attrib_type Attribute;
unsigned nextReply;
} FIDO_message_type;
typedef
FIDO_message_type * FIDO_message_ptr_type;
typedef
struct directory_entry_struct
{
char file[8];
char ext[3];
unsigned char attribute;
char reserved[10];
unsigned time;
unsigned date;
unsigned starting_cluster;
unsigned long size;
} directory_entry_type;
typedef
directory_entry_type * directory_entry_ptr_type;
typedef
struct drive_parm_struct
{
unsigned char drive_number;
unsigned char unit_number;
unsigned bytes_per_sector;
unsigned char sectors_per_cluster;
unsigned char shift_factor;
unsigned reserved_sectors;
unsigned char number_of_FAT_copies;
unsigned n_root_directory_entries;
unsigned first_data_sector;
unsigned n_clusters;
unsigned sectors_per_FAT;
} drive_parm_type;
typedef
drive_parm_type far * drive_parm_ptr_type;
enum token_type_enum
{
token_eof,
token_comment,
token_eol,
token_normal
};
typedef
struct tosslog_list_struct
{
struct tosslog_list_struct * next;
char area[1];
} tosslog_list_type;
typedef tosslog_list_type * tosslog_list_ptr_type;
void add_token_char(void);
void advance_to_next_line(void);
void * allocate_memory(unsigned n_bytes);
void check_for_grunged_messages(unsigned from1msg);
void check_message(void);
void close_file(FILE * * file);
unsigned long cluster_to_sector(unsigned cluster);
unsigned current_cluster;
void delete_grunged_messages(void);
void drop_fast_mode(void);
directory_entry_ptr_type get_directory_entry(void);
unsigned get_message_number(void);
void get_next_char(void);
unsigned get_token(void);
unsigned grunged(char * s,
unsigned length,
unsigned ok_count);
void initialize(unsigned argc,
char * argv[]);
void load_bad_message_table(void);
void load_drive_parms(char * file);
void load_tosslog_list(void);
void log_message(unsigned level,
char * fmt,
...);
FILE * open_file(char * filename,
char * mode);
void next_cluster(void);
void parse_parms(unsigned argc,
char * argv[]);
unsigned process_echo(void);
void process_header(void);
void read_cluster(unsigned cluster);
void read_disk(unsigned long sector,
unsigned n_sectors,
void * buffer);
FIDO_message_ptr_type read_message(void);
void read_sector(unsigned long sector_number);
void shut_down(unsigned return_code);
void synchronize_cluster(void);
FILE * areas_in;
char * areas_in_name;
char * bad_directory_name;
char bad_echo_name[9];
unsigned char bad_message_table[1000];
unsigned bytes_per_sector;
int c;
unsigned long cluster_0_sector;
void * cluster_buffer;
unsigned cluster_in_buffer;
unsigned current_relative_cluster;
unsigned current_FAT_sector;
char directory[MAX_FILENAME_LENGTH];
unsigned * directory_cluster;
unsigned directory_entries_per_cluster;
unsigned * directory_index;
unsigned drive;
drive_parm_ptr_type drive_parms;
char echo_name[MAX_ECHONAME_LENGTH];
unsigned fast_mode;
void * FAT_buffer;
struct ffblk ff_blk;
unsigned long first_FAT_sector;
unsigned found_grunged_message;
union REGS inregs;
unsigned line_number;
unsigned log_level;
FIDO_message_type message;
char message_filename[MAX_FILENAME_LENGTH];
unsigned n_clusters;
unsigned n_grunged;
unsigned ok_date;
unsigned ok_from;
unsigned ok_subject;
unsigned ok_to;
union REGS outregs;
void * sector_buffer;
unsigned long sectors_per_cluster;
struct SREGS segregs;
unsigned skip_passthrus;
FILE * temp_file;
char temp_filename[13];
unsigned test_mode;
char token[MAX_TOKEN_SIZE];
char * token_end;
unsigned token_length;
unsigned token_type;
tosslog_list_ptr_type tosslog_list;
char * tosslog_name;
unsigned zlDate;
unsigned zlFrom;
unsigned zlSubject;
unsigned zlTo;
void main (unsigned argc,
char * argv[])
{
char * c;
unsigned i;
initialize(argc, argv);
if (areas_in_name)
{
areas_in = open_file(areas_in_name, "r");
get_next_char();
process_header();
while (process_echo());
};
for (i=1; i<argc; i++)
{
if ((strnicmp(argv[i], "-d", 2) == 0) &&
(strnicmp(argv[i], "-date:", 6) != 0))
{
strcpy(directory, &argv[i][2]);
strcpy(echo_name, directory);
c = strrchr(echo_name, '\\');
if (c++)
strcpy(echo_name, c);
check_for_grunged_messages(0u);
};
};
close_file(&areas_in);
close_file(&temp_file);
delete_grunged_messages();
shut_down(n_grunged > 0);
}
void add_token_char(void)
{
if (token_length++ < MAX_TOKEN_SIZE)
*token_end++ = (char) c;
*token_end = 0x00;
return;
}
void advance_to_next_line()
{
while ((token_type != token_eol) && (token_type != token_eof))
get_token();
if (token_type == token_eol)
get_token();
return;
};
void * allocate_memory(unsigned n_bytes)
{
void * buffer;
if ((buffer = malloc(n_bytes)) == NULL)
{
log_message(0, "Error: Out of memory.\n");
shut_down(2);
};
return(buffer);
}
void check_for_grunged_messages(unsigned from1msg)
{
unsigned count;
unsigned current_message_number;
unsigned done;
char * dot;
unsigned lowest_message;
FILE * message_file;
unsigned n_messages;
log_message(3, "Processing echo: %16s .", echo_name);
lowest_message = 0u;
if (from1msg)
{
strcpy(message_filename, directory);
strcat(message_filename, "\\1.msg");
if ((message_file = fopen(message_filename, "rb")) != NULL)
{
fread(&message, sizeof(message), 1, message_file);
close_file(&message_file);
lowest_message = message.replyTo;
};
};
count = 100u;
n_messages = 0u;
found_grunged_message = 0u;
strcpy(message_filename, directory);
strcat(message_filename, "\\*.msg");
if (fast_mode)
load_drive_parms(message_filename);
done = findfirst(message_filename, &ff_blk, 0);
if (!done && fast_mode)
{
current_relative_cluster = 0u;
current_cluster = *directory_cluster;
};
while (!done)
{
strcpy(message_filename, directory);
strcat(message_filename, "\\");
strcat(message_filename, ff_blk.ff_name);
dot = strchr(ff_blk.ff_name, '.');
*dot = '\000';
current_message_number = atoi(ff_blk.ff_name);
*dot = '.';
if (current_message_number > lowest_message)
check_message();
n_messages++;
if (!count--)
{
count = 100u;
if (found_grunged_message)
log_message(4, "x");
else
log_message(4, ".");
found_grunged_message = 0u;
};
if (kbhit())
{
if (getche() == 0x03)
shut_down(2);
};
done = findnext(&ff_blk);
};
if (kbhit())
{
if (getche() == 0x03)
shut_down(2);
};
if (fast_mode)
{
free(cluster_buffer);
cluster_buffer = NULL;
free(sector_buffer);
sector_buffer = NULL;
free(FAT_buffer);
FAT_buffer = NULL;
};
if (found_grunged_message)
log_message(4, "x");
else
log_message(4, ".");
log_message(4, " (%u messages)", n_messages);
log_message(3, "\n");
return;
}
void check_message()
{
FIDO_message_ptr_type msg;
msg = read_message();
if (grunged(msg->fromUserName, sizeof(msg->fromUserName), ok_from) ||
grunged(msg->toUserName, sizeof(msg->toUserName), ok_to) ||
grunged(msg->subject, sizeof(msg->subject), ok_subject) ||
grunged(msg->dateTime, sizeof(msg->dateTime), ok_date) ||
(zlFrom && (msg->fromUserName[0] == '\000')) ||
(zlTo && (msg->toUserName[0] == '\000')) ||
(zlSubject && (msg->subject[0] == '\000')) ||
(zlDate && (msg->dateTime[0] == '\000')))
{
found_grunged_message = 1u;
n_grunged++;
fprintf(temp_file, "%s,%s\n", message_filename, echo_name);
};
return;
}
void close_file(FILE * * file)
{
if (*file)
{
fclose(*file);
*file = NULL;
};
return;
}
unsigned long cluster_to_sector(unsigned cluster)
{
return(cluster_0_sector + (sectors_per_cluster * ((unsigned long) cluster)));
}
void delete_grunged_messages()
{
char buffer[512];
char * c;
char * echo;
struct ftime ft;
FILE * in;
unsigned item_count;
unsigned message_number;
FILE * out;
char filename[MAX_FILENAME_LENGTH];
temp_file = open_file(temp_filename, "r");
while (fgets(token, MAX_TOKEN_SIZE, temp_file))
{
echo = strchr(token, ',');
*echo++ = '\000';
*strchr(echo, '\n') = '\000';
strcpy(message_filename, token);
strcpy(echo_name, echo);
log_message(2, "Message \"%s\" in echo \"%s\" is grunged",
message_filename, echo_name);
memset(echo_name, 0, MAX_ECHONAME_LENGTH);
for (c = echo_name; *echo; echo++)
if ( (*echo == '!') ||
((*echo >= '#') && (*echo <= ')')) ||
(*echo == '-') ||
((*echo >= '0') && (*echo <= '9')) ||
(*echo == '@') ||
((*echo >= 'A') && (*echo <= 'Z')) ||
((*echo >= '^') && (*echo <= '[')) ||
((*echo >= ']') && (*echo <= '~')))
*c++ = *echo;
if (strlen(echo_name) == 0)
strcpy(echo_name,"[NULL]");
if (test_mode)
log_message(2, ".\n");
else
{
if (bad_directory_name)
{
message_number = get_message_number();
if (message_number < 1000u)
{
sprintf(filename, "%s\\%s.%03u",
bad_directory_name, bad_echo_name, message_number);
log_message(2, ".\n");
log_message(2," (Moved to %s.)\n", filename);
in = open_file(message_filename, "rb");
out = open_file(filename, "wb");
while ((item_count = fread(buffer, 1, 512, in)) != 0)
fwrite(buffer, 1, item_count, out);
getftime(fileno(in), &ft);
close_file(&in);
fflush(out);
setftime(fileno(out), &ft);
close_file(&out);
unlink(message_filename);
}
else
{
log_message(2, ".\n");
log_message(2, " (Deleted because it could not be moved.)\n");
unlink(message_filename);
};
}
else
{
if (unlink(message_filename) == 0)
log_message(2, " (remove OK).\n");
else
log_message(2, " (could not remove).\n");
};
};
};
close_file(&temp_file);
return;
}
void drop_fast_mode()
{
log_message(0, "\n");
log_message(0, "Note: Fast mode disabled\n");
fast_mode = 0u;
if (cluster_buffer)
free(cluster_buffer);
cluster_buffer = NULL;
if (sector_buffer)
free(sector_buffer);
sector_buffer = NULL;
if (FAT_buffer)
free(FAT_buffer);
FAT_buffer = NULL;
return;
}
directory_entry_ptr_type get_directory_entry()
{
directory_entry_ptr_type dir;
synchronize_cluster();
dir = (directory_entry_ptr_type) cluster_buffer;
return(&dir[*directory_index % directory_entries_per_cluster]);
}
unsigned get_message_number()
{
unsigned i;
unsigned char * up;
if (strnicmp(echo_name, bad_echo_name, 8) != 0)
load_bad_message_table();
for (i = 0u, up = bad_message_table; i < 1000u; i++, up++)
{
if (*up == 0)
{
*up = 1u;
return(i);
};
};
return(1000u);
}
void get_next_char(void)
{
c = fgetc(areas_in);
if (c == '\n')
line_number++;
return;
}
unsigned get_token()
{
token_length = 0u;
token_end = token;
*token_end = 0x00;
while ((c == ' ') || (c == 0x09))
get_next_char();
if (c == EOF)
{
token_type = token_eof;
return(token_type);
};
if ((c == ';') || (c == '%') || (c == '-'))
{
token_type = token_comment;
while ((c!='\n') && (c!=EOF))
{
add_token_char();
get_next_char();
};
return(token_type);
};
if (c == '\n')
{
token_type = token_eol;
get_next_char();
return(token_type);
};
token_type = token_normal;
while ((c!=' ') && (c!=0x09) && (c!='\n') && (c!=EOF))
{
add_token_char();
get_next_char();
};
return(token_type);
}
unsigned grunged(char * s,
unsigned length,
unsigned ok_count)
{
while (*s)
{
if ((!length--) || ((*s++ & 0x80) && !ok_count--))
return(1u);
};
return(0u);
}
void initialize(unsigned argc,
char * argv[])
{
line_number = 1u;
log_level = 4u;
n_grunged = 0u;
fast_mode = 0u;
test_mode = 0u;
ok_date = 0u;
ok_from = 0u;
ok_subject = 0u;
ok_to = 0u;
zlDate = 0u;
zlFrom = 0u;
zlSubject = 0u;
zlTo = 0u;
cluster_buffer = NULL;
sector_buffer = NULL;
FAT_buffer = NULL;
areas_in_name = NULL;
areas_in = NULL;
tosslog_name = NULL;
tosslog_list = NULL;
temp_file = NULL;
directory_index = (unsigned *) &ff_blk.ff_reserved[13];
directory_cluster = (unsigned *) &ff_blk.ff_reserved[15];
strcpy(bad_echo_name, "");
tmpnam(temp_filename);
parse_parms(argc, argv);
load_tosslog_list();
if (argc < 2u)
{
log_message(0, "\n\n\n\n\n");
log_message(0, "Usage: GMD [-a<Areas.Bbs>] [-b<bad_path>] [-e<toss_log>] [-d<directory>]...\n");
log_message(0, " [switches]\n");
log_message(0, " Where: <Areas.Bbs> is the name of the QMail Areas.Bbs file.\n");
log_message(0, " <directory> is a message area directory to be manually\n");
log_message(0, " checked for grunged messages.\n");
log_message(0, " <toss_log> is a list of areas to process.\n");
log_message(0, " <bad_path> is the path where grunged messages are copied.\n");
log_message(0, " Switches: -date:n - Permit \'n\' bad characters in \'date\' field.\n");
log_message(0, " -from:n - Permit \'n\' bad characters in \'from\' field.\n");
log_message(0, " -subject:n - Permit \'n\' bad characters in \'subject\' field.\n");
log_message(0, " -to:n - Permit \'n\' bad characters in \'to\' field.\n");
log_message(0, " -zlDate - Treat zero length \'date\' fields as grunged.\n");
log_message(0, " -zlFrom - Treat zero length \'from\' fields as grunged.\n");
log_message(0, " -zlSubject - Treat zero length \'subject\' fields as grunged.\n");
log_message(0, " -zlTo - Treat zero length \'to\' fields as grunged.\n");
log_message(0, " -l:n - Set logging detail level.\n");
log_message(0, " -f - Sets fast mode by bypassing DOS for reads.\n");
log_message(0, " -p - Skip passthru areas when -e is specified.\n");
log_message(0, " -t - Sets test mode. No messages are deleted.\n");
log_message(0, " Function: GMD deletes grunged messages from the directories listed\n");
log_message(0, " in <Areas.Bbs>. Additional directories can be manually\n");
log_message(0, " specified with -d switches.\n");
shut_down(2);
};
log_message(1, "Grunged Message Delete utility. Written by David Troendle (1:396/5).\n");
log_message(1, "Tested, documented and distributed by John Souvestre (1:396/1).\n");
log_message(1, "Version 2.0, February 24, 1991.\n");
log_message(1, "\n");
log_message(1, "Scanning for grunged messages.\n");
temp_file = open_file(temp_filename, "w");
return;
}
void load_bad_message_table()
{
unsigned done;
char * ext;
char * ext2;
char file[MAX_FILENAME_LENGTH];
unsigned i;
unsigned char * up;
for (i = 0u, up = bad_message_table; i < 1000u; i++)
*up++ = 0;
memcpy(bad_echo_name, echo_name, 8);
bad_echo_name[8] = '\000';
strcpy(file, bad_directory_name);
strcat(file, "\\");
strcat(file, bad_echo_name);
strcat(file, ".*");
done = findfirst(file, &ff_blk, FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_DIREC);
while (!done)
{
if ((ext = ext2 = strrchr(ff_blk.ff_name, '.')) != NULL)
{
ext++;
ext2++;
while (*ext)
{
if (!isdigit(*ext))
break;
ext++;
};
if (*ext == '\000')
bad_message_table[atoi(ext2)] = 1u;
};
done = findnext(&ff_blk);
};
return;
}
void load_drive_parms(char * file)
{
if (file[1] == ':')
drive = tolower(file[0]) - 'a';
else
drive = getdisk();
inregs.h.ah = 0x32;
inregs.h.dl = drive + 1u;
intdosx(&inregs, &outregs, &segregs);
if (outregs.h.al == 0xff)
{
drop_fast_mode();
return;
};
drive_parms = MK_FP(segregs.ds, outregs.x.bx);
bytes_per_sector = drive_parms->bytes_per_sector;
sectors_per_cluster =
(unsigned long) drive_parms->sectors_per_cluster + 1u;
directory_entries_per_cluster =
(bytes_per_sector * ((unsigned) sectors_per_cluster)) /
sizeof(directory_entry_type);
n_clusters = drive_parms->n_clusters;
cluster_0_sector =
((unsigned long) drive_parms->first_data_sector) -
2ul * sectors_per_cluster;
first_FAT_sector =
(unsigned long) drive_parms->reserved_sectors;
cluster_buffer =
allocate_memory(bytes_per_sector * ((unsigned) sectors_per_cluster));
FAT_buffer = allocate_memory(2u * bytes_per_sector);
sector_buffer = allocate_memory(bytes_per_sector);
current_FAT_sector = 0u;
cluster_in_buffer = 0u;
return;
}
void load_tosslog_list(void)
{
unsigned len;
tosslog_list_ptr_type tosslog_entry;
FILE * tosslog_file;
if (!tosslog_name)
return;
if ((tosslog_file = fopen(tosslog_name, "r")) == NULL)
return;
while (fgets(token, MAX_TOKEN_SIZE, tosslog_file))
{
len = strlen(token);
if (len)
{
if (token[len-1] == '\n')
token[--len] = '\000';
};
if (len)
{
tosslog_entry = (tosslog_list_ptr_type)
allocate_memory(sizeof(tosslog_list_type) + len);
strcpy(tosslog_entry->area, token);
tosslog_entry->next = tosslog_list;
tosslog_list = tosslog_entry;
};
};
close_file(&tosslog_file);
return;
}
void log_message(unsigned level,
char * fmt,
...)
{
va_list argptr;
va_start(argptr, fmt);
if (level <= log_level)
{
if (level <= 1)
vfprintf(stderr, fmt, argptr);
else
vprintf(fmt, argptr);
};
va_end(argptr);
return;
}
FILE * open_file(char * filename,
char * mode)
{
FILE * file;
if ((file = fopen(filename, mode)) == NULL)
{
log_message(0, "Error: Could not open file \"%s\" for mode \"%s\".\n",
filename, mode);
shut_down(2);
};
return(file);
}
void next_cluster()
{
unsigned long offset;
unsigned sector;
unsigned sector_offset;
unsigned temp;
if (n_clusters <= SMALL_FAT_MAX_CLUSTERS)
{
offset = ((unsigned long) current_cluster) * 3ul;
offset /= 2u;
}
else
offset = ((unsigned long) current_cluster) * 2ul;
sector = ((unsigned) offset) / bytes_per_sector;
sector_offset = ((unsigned) offset) % bytes_per_sector;
sector = sector + ((unsigned) first_FAT_sector);
if (current_FAT_sector != sector)
{
read_disk((unsigned long) sector, 2, FAT_buffer);
current_FAT_sector = sector;
};
if (n_clusters < SMALL_FAT_MAX_CLUSTERS)
{
temp = *((unsigned *) (((char *) FAT_buffer) + sector_offset));
if (current_cluster & 0x0001)
current_cluster = temp >> 4u;
else
current_cluster = temp && 0x0fff;
}
else
current_cluster = *((unsigned *) (((char *) FAT_buffer) + sector_offset));
current_relative_cluster++;
return;
}
void parse_parms(unsigned argc,
char * argv[])
{
unsigned i;
for (i=1; i<argc; i++)
{
if (strnicmp(argv[i], "-a", 2) == 0)
{
areas_in_name = &argv[i][2];
continue;
};
if (strnicmp(argv[i], "-b", 2) == 0)
{
bad_directory_name = &argv[i][2];
continue;
};
if (strnicmp(argv[i], "-date:", 6) == 0)
{
ok_date = atoi(argv[i] + 6);
continue;
};
if (strnicmp(argv[i], "-e", 2) == 0)
{
tosslog_name = &argv[i][2];
continue;
};
if (strnicmp(argv[i], "-p", 2) == 0)
{
skip_passthrus = 1u;
continue;
};
if (strnicmp(argv[i], "-l:", 3) == 0)
{
log_level = atoi(argv[i] + 3);
if (log_level > 4)
{
log_message(0, "Invalid error log level \"%s\".\n", argv[i]);
shut_down(2);
};
continue;
};
if (strnicmp(argv[i], "-from:", 6) == 0)
{
ok_from = atoi(argv[i] + 6);
continue;
};
if (strnicmp(argv[i], "-subject:", 9) == 0)
{
ok_subject = atoi(argv[i] + 9);
continue;
};
if (strnicmp(argv[i], "-to:", 4) == 0)
{
ok_to = atoi(argv[i] + 4);
continue;
};
if (strnicmp(argv[i], "-d", 2) == 0)
continue;
if (stricmp(argv[i], "-f") == 0)
{
fast_mode = 1u;
continue;
};
if (stricmp(argv[i], "-t") == 0)
{
test_mode = 1u;
continue;
};
if (stricmp(argv[i], "-zlDate") == 0)
{
zlDate = 1u;
continue;
};
if (stricmp(argv[i], "-zlFrom") == 0)
{
zlFrom = 1u;
continue;
};
if (stricmp(argv[i], "-zlSubject") == 0)
{
zlSubject = 1u;
continue;
};
if (stricmp(argv[i], "-zlTo") == 0)
{
zlTo = 1u;
continue;
};
log_message(0, "Error: Unknown switch \"%s\".\n", argv[i]);
shut_down(2);
};
return;
}
unsigned process_echo()
{
unsigned found;
unsigned passthru_area;
tosslog_list_ptr_type tosslog_entry;
if (token_type == token_eof)
return(0u);
if (token_type == token_comment)
get_token();
if (token_type == token_eol)
{
get_token();
return(1u);
};
passthru_area = token[0] == '#';
if (passthru_area)
{
if (skip_passthrus)
{
advance_to_next_line();
return(1u);
};
strcpy(token, &token[1]);
};
strcpy(directory, token);
get_token();
if (token_type != token_normal)
{
log_message(0, "Error: Invalid syntax on line %u.\n", line_number);
shut_down(2);
};
strcpy(echo_name, token);
found = tosslog_name == NULL;
for (tosslog_entry = tosslog_list;
!found && (tosslog_entry != NULL);
tosslog_entry = tosslog_entry->next)
{
found = stricmp(echo_name, tosslog_entry->area) == 0;
};
if ((tosslog_name != NULL) && found)
check_for_grunged_messages(!passthru_area);
else
if ((tosslog_name == NULL) && !passthru_area)
check_for_grunged_messages(0u);
advance_to_next_line();
return(1u);
}
void process_header()
{
unsigned title_encountered;
title_encountered = 0u;
while (((title_encountered && ((c == ';') || (c == '\n'))) ||
!title_encountered) && (c != EOF))
{
if (!title_encountered && ((c != ';') && (c != '\n')))
title_encountered = 1u;
while ((c != '\n') && (c != EOF))
get_next_char();
if (c != EOF)
get_next_char();
};
get_token();
return;
}
void read_cluster(unsigned cluster)
{
if (cluster == cluster_in_buffer)
return;
read_disk(cluster_to_sector(cluster),
(unsigned) sectors_per_cluster,
cluster_buffer);
cluster_in_buffer = cluster;
return;
}
void read_disk(unsigned long sector,
unsigned n_sectors,
void * buffer)
{
struct
{
unsigned long sector_number;
unsigned n_sectors;
void far * buffer;
} extended_parm_block;
inregs.h.al = drive;
if (sector > 65535ul)
{
inregs.x.cx = 0xffff;
extended_parm_block.sector_number = sector;
extended_parm_block.n_sectors = n_sectors;
extended_parm_block.buffer = buffer;
inregs.x.bx = FP_OFF(&extended_parm_block);
segregs.ds = FP_SEG(&extended_parm_block);
}
else
{
inregs.x.cx = n_sectors;
inregs.x.dx = (unsigned) sector;
inregs.x.bx = FP_OFF(buffer);
segregs.ds = FP_SEG(buffer);
};
int86x(0x25, &inregs, &outregs, &segregs);
if (outregs.x.cflag)
{
log_message(0, "Error: Could not read sector %lu on drive %c:\n",
sector, drive + 'a');
shut_down(2);
};
return;
}
#define ROOT_DIRECTORY (*directory_cluster == 0)
FIDO_message_ptr_type read_message()
{
directory_entry_ptr_type dir;
char * dot;
char file[32];
FILE * message_file;
strcpy(file, ff_blk.ff_name);
if ((dot = strrchr(file, '.')) != NULL)
*dot = '\000';
strcat(file," ");
if (fast_mode && (!ROOT_DIRECTORY))
{
dir = get_directory_entry();
if ((dir->time != ff_blk.ff_ftime) ||
(dir->date != ff_blk.ff_fdate) ||
(dir->size != ff_blk.ff_fsize) ||
(memicmp(dir->file, file, 8) != 0))
{
drop_fast_mode();
}
else
{
read_sector(cluster_to_sector(dir->starting_cluster));
return((FIDO_message_ptr_type) sector_buffer);
};
};
message_file = open_file(message_filename, "rb");
fread(&message, sizeof(message), 1, message_file);
close_file(&message_file);
return(&message);
}
#undef ROOT_DIRECTORY
void read_sector(unsigned long sector_number)
{
read_disk(sector_number, 1, sector_buffer);
return;
}
void shut_down(unsigned return_code)
{
close_file(&temp_file);
unlink(temp_filename);
close_file(&areas_in);
exit(return_code);
return;
}
void synchronize_cluster()
{
unsigned required_relative_cluster;
required_relative_cluster = *directory_index / directory_entries_per_cluster;
while (current_relative_cluster < required_relative_cluster)
next_cluster();
read_cluster(current_cluster);
return;
}